﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Text.Unicode;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CL_Sales
{
    public class RequestCLPeakHourData
    {
        private readonly HttpClient client;
        private readonly int waittime;
        private readonly DayPartItem dayPart;

        public RequestCLPeakHourData(HttpClient client, int waittime, DayPartItem dayPart)
        {
            this.client = client;
            this.waittime = waittime;
            this.dayPart = dayPart;
        }

        public async Task<HttpResponseMessage> GetPeakHourData(DateTime start, DateTime end)
        {
            //step1
            string datestr = "2 ";
            datestr = datestr + start.ToString("yyyy/M/d");
            datestr = datestr + " ";
            datestr = datestr + end.ToString("yyyy/M/d");
            HttpResponseMessage response = await client.SendAsync(RequestPeakHourStep1(datestr));
            await Task.Delay(waittime);
            response.EnsureSuccessStatusCode();
            var responseContent = await response.Content.ReadAsStringAsync();
            //step2 直到出现初步数据为止
            for (int i = 0; i < 20; i++)
            {
                response = await client.SendAsync(RequestPeakHourStep2(datestr));
                await Task.Delay(waittime);
                response.EnsureSuccessStatusCode();
                responseContent = await response.Content.ReadAsStringAsync();
                if (responseContent.Contains("Export to different format") || responseContent.Contains("导出到不同格式"))
                {
                    break;
                }
            }
            //step3  全选所有时间段          
            string viewState, xml, statePath, scid;
            //viewState
            string pattern = @"stateID=""([^""]+)""";
            Match match = Regex.Match(responseContent, pattern);
            viewState = match.Groups[1].Value;
            //xml
            xml = GetXml(responseContent);
            //statePath
            pattern = @"vid=""([^""]+)""";
            match = Regex.Match(responseContent, pattern);
            statePath = match.Groups[1].Value;
            //scid
            pattern = @"obips_scid=""([^""]+)""";
            match = Regex.Match(responseContent, pattern);
            scid = match.Groups[1].Value;
            //viewid
            pattern = @"viewStatePath"":""([^""]*)""";
            match = Regex.Match(responseContent, pattern);
            string viewid = match.Groups[1].Value;
            //开始重载
            for (int i = 0; i < 20; i++)
            {
                response = await client.SendAsync(RequestPeakHourStep3(viewState, xml, scid, viewid));
                await Task.Delay(waittime);
                response.EnsureSuccessStatusCode();
                responseContent = await response.Content.ReadAsStringAsync();
                if (responseContent.Contains("Export to different format") || responseContent.Contains("导出到不同格式"))
                {
                    break;
                }
            }

            //step4 获取详尽每日数据前准备
            pattern = @"ViewState=([^&]*)&";
            match = Regex.Match(responseContent, pattern);
            viewState = match.Groups[1].Value;

            xml = GetXml(responseContent);

            pattern = @"vid=""([^""]+)""";
            match = Regex.Match(responseContent, pattern);
            string reloadTargets = match.Groups[1].Value;

            pattern = @"(saw_\d+(_\d+)*)_JSDataLayout";
            match = Regex.Match(responseContent, pattern);
            string masterClientID = match.Groups[1].Value;

            pattern = @"(saw_.*?)_3_0_Grp";
            match = Regex.Match(responseContent, pattern);
            string childViewId = match.Groups[1].Value;

            response = await client.SendAsync(RequestPeakHourStep4(viewState, xml, reloadTargets, masterClientID, childViewId, scid));
            await Task.Delay(waittime);
            response.EnsureSuccessStatusCode();
            responseContent = await response.Content.ReadAsStringAsync();

            //step5 正式开始获取每日详尽数据

            //viewState可以用step4的

            xml = GetXml(responseContent);

            //reloadTargets可以用step4

            pattern = @"p:([a-z0-9]+)~";
            match = Regex.Match(responseContent, pattern);
            string pageid = match.Groups[1].Value;

            pattern = @"sid=""([^""]+)""";
            match = Regex.Match(responseContent, pattern);
            string sid = match.Groups[1].Value;

            response = await client.SendAsync(RequestPeakHourStep5(viewState, xml, reloadTargets, pageid, sid));
            await Task.Delay(waittime);
            response.EnsureSuccessStatusCode();
            responseContent = await response.Content.ReadAsStringAsync();


            //step 6 获得数据并显示

            pattern = @"ViewState=([^&]*)&";
            match = Regex.Match(responseContent, pattern);
            string viewState2 = match.Groups[1].Value;

            pattern = @"vid=""([^""]+)""";
            match = Regex.Match(responseContent, pattern);
            string vid = match.Groups[1].Value;

            xml = GetXml(responseContent);

            for (int i = 0; i < 20; i++)
            {
                response = await client.SendAsync(RequestPeakHourStep6(viewState2, viewState, xml, pageid, vid, scid));
                await Task.Delay(waittime);
                response.EnsureSuccessStatusCode();
                responseContent = await response.Content.ReadAsStringAsync();
                if (responseContent.Contains("Export to different format") || responseContent.Contains("导出到不同格式"))
                {
                    break;
                }
            }

            //step7 下载前准备
            pattern = @"sid=""([^""]+)""";
            match = Regex.Match(responseContent, pattern);
            sid = match.Groups[1].Value;

            pattern = @"ViewState=([^&]*)&";
            match = Regex.Match(responseContent, pattern);
            viewState = match.Groups[1].Value;

            //获取下载准备需要的post数据   
            xml = GetXml(responseContent);

            response = await client.SendAsync(RequestPeahHourStep7(vid, sid, viewState, xml));
            await Task.Delay(waittime);
            response.EnsureSuccessStatusCode();
            responseContent = await response.Content.ReadAsStringAsync();

            //step8 确定是否可以下载
            pattern = @"obips\.download\.downloadStatus\('([^']*)'";
            match = Regex.Match(responseContent, pattern);
            string downloadStatus = match.Groups[1].Value;

            for (int i = 0; i < 20; i++)
            {
                response = await client.SendAsync(RequestPeakHourStep8(downloadStatus, scid));
                await Task.Delay(waittime);
                response.EnsureSuccessStatusCode();
                responseContent = await response.Content.ReadAsStringAsync();
                if (responseContent.Contains("done"))
                {
                    break;
                }
            }

            //step 9下载数据文件
            response = await client.SendAsync(RequestPeakHourStep9(downloadStatus));
            response.EnsureSuccessStatusCode();
            return response;
        }

        /// <summary>
        /// 进入登录数据库界面
        /// </summary>
        private HttpRequestMessage RequestPeakHourStep1(string dateStr)
        {
            var message = new HttpRequestMessage(HttpMethod.Post, $"https://biee.mcdonalds.cn/analytics/saw.dll?PortalPages&PortalPath=/shared/Dashboard/_portal/Peak%20Hour%20Period&Action=Navigate&Options=dfr&syndicate=siebel&Page={dayPart.Value}%20by%20Store(DB)");
            message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36");
            message.Content = new FormUrlEncodedContent(new[]
           {
                new KeyValuePair<string, string>("NQUser","Store"),
                new KeyValuePair<string, string>("NQPassword","Pass1234"),
                new KeyValuePair<string, string>("P0","4"),
                new KeyValuePair<string, string>("P1","eq"),
                new KeyValuePair<string, string>("P2","\"Operation\".\"Store Key\""),
                new KeyValuePair<string, string>("P3","69 \"1420411\" \"1420396\" \"1420363\" \"1420332\" \"1420322\" \"1420079\" \"1420040\" "),
                new KeyValuePair<string, string>("P4","bet"),
                new KeyValuePair<string, string>("P5","\"Time\".\"Calendar Date\""),
                new KeyValuePair<string, string>("P6",dateStr),
                new KeyValuePair<string, string>("P7","eq"),
                new KeyValuePair<string, string>("P8","\"Operation\".\"Store\""),
                new KeyValuePair<string, string>("P9","203 1420411 Maoming Youcheng 10th Rd 1420396 Maoming Xiyue Middle Rd 1420363 Enping Xinping Middle Rd 1420332 Jiangmen Baishi Ave 1420322 Jiangmen Kaiping Ave 1420079 Jiangmen Donghu 1420040 Kaiping Tanjiang ")
            });
            return message;
        }

        /// <summary>
        /// 进入展示数据界面
        /// </summary>
        private HttpRequestMessage RequestPeakHourStep2(string dateStr)
        {
            var message = new HttpRequestMessage(HttpMethod.Post, "https://biee.mcdonalds.cn/analytics/saw.dll?PortalPages");
            message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36");
            message.Content = new FormUrlEncodedContent(new[]
           {
                new KeyValuePair<string, string>("Page",$"{dayPart.Value2} by Store(DB)"),
                new KeyValuePair<string, string>("Action","Navigate"),
                new KeyValuePair<string, string>("PortalPath","/shared/Dashboard/_portal/Peak Hour Period"),
                new KeyValuePair<string, string>("P0","4"),
                new KeyValuePair<string, string>("P1","eq"),
                new KeyValuePair<string, string>("P2","\"Operation\".\"Store Key\""),
                new KeyValuePair<string, string>("syndicate","siebel"),
                new KeyValuePair<string, string>("P3","69 \"1420411\" \"1420396\" \"1420363\" \"1420332\" \"1420322\" \"1420079\" \"1420040\" "),
                new KeyValuePair<string, string>("P4","bet"),
                new KeyValuePair<string, string>("P5","\"Time\".\"Calendar Date\""),
                new KeyValuePair<string, string>("P6",dateStr),
                new KeyValuePair<string, string>("P7","eq"),
                new KeyValuePair<string, string>("P8","\"Operation\".\"Store\""),
                new KeyValuePair<string, string>("Options","dfr"),
                new KeyValuePair<string, string>("P9","203 1420411 Maoming Youcheng 10th Rd 1420396 Maoming Xiyue Middle Rd 1420363 Enping Xinping Middle Rd 1420332 Jiangmen Baishi Ave 1420322 Jiangmen Kaiping Ave 1420079 Jiangmen Donghu 1420040 Kaiping Tanjiang ")
            });
            return message;
        }

        /// <summary>
        /// 获取每日详尽数据前准备
        /// </summary>
        /// <param name="dateStr"></param>
        /// <param name="viewState"></param>
        /// <param name="xml"></param>
        /// <param name="statePath"></param>
        /// <param name="scid"></param>
        /// <returns></returns>
        private HttpRequestMessage RequestPeakHourStep4(string viewState, string xml, string reloadTargets, string masterClientID, string childViewId, string scid)
        {
            var message = new HttpRequestMessage(HttpMethod.Post, "https://biee.mcdonalds.cn/analytics/saw.dll?ReloadDashboard");
            message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36");
            message.Content = new FormUrlEncodedContent(new[]
           {
                new KeyValuePair<string, string>("ViewState",viewState),
                new KeyValuePair<string, string>("Done",$"PortalPages&PortalPath=%2Fshared%2FDashboard%2F_portal%2FPeak%20Hour%20Period&Page={dayPart.Value}%20by%20Store(DB)&ViewState={viewState}"),
                new KeyValuePair<string, string>("ClientStateXml",xml),
                new KeyValuePair<string, string>("fmapId","GxBopg"),
                new KeyValuePair<string, string>("bNotSaveCommand","true"),
                new KeyValuePair<string, string>("reloadTargets",reloadTargets),
                new KeyValuePair<string, string>("Page",$"{dayPart.Value2} by Store(DB)"),
                new KeyValuePair<string, string>("PortalPath","/shared/Dashboard/_portal/Peak Hour Period"),
                new KeyValuePair<string, string>("Action","FetchJSDataLayout"),
                new KeyValuePair<string, string>("ViewID",$"{reloadTargets}~v:compoundView!1~v:pivotTableView!1"),
                new KeyValuePair<string, string>("refreshViewIDs",$"{reloadTargets}~v:compoundView!1~v:pivotTableView!1"),
                new KeyValuePair<string, string>("TargetViewReadOnlyAjax","true"),
                new KeyValuePair<string, string>("MasterClientID",masterClientID),
                new KeyValuePair<string, string>("ChildViewId",childViewId),
                new KeyValuePair<string, string>("SectionSlice","0"),
                new KeyValuePair<string, string>("bIsChart",""),
                new KeyValuePair<string, string>("_scid",scid),
                new KeyValuePair<string, string>("icharset","utf-8")
            });
            return message;
        }


        /// <summary>
        /// 全选时间段
        /// </summary>
        /// <param name="dateStr"></param>
        /// <param name="stateID"></param>        
        /// <returns></returns>
        private HttpRequestMessage RequestPeakHourStep3(string viewState, string xml, string scid, string viewid)
        {
            var message = new HttpRequestMessage(HttpMethod.Post, "https://biee.mcdonalds.cn/analytics/saw.dll?ReloadDashboard");
            message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36");
            message.Content = new FormUrlEncodedContent(new[]
           {
                new KeyValuePair<string, string>("ViewState",viewState),
                new KeyValuePair<string, string>("Done",$"PortalPages&PortalPath=%2Fshared%2FDashboard%2F_portal%2FPeak%20Hour%20Period&Page={dayPart.Value}%20by%20Store(DB)&ViewState={viewState}"),
                new KeyValuePair<string, string>("ClientStateXml",xml),
                new KeyValuePair<string, string>("fmapId","GxBopg"),
                new KeyValuePair<string, string>("reloadTargets","all"),
                new KeyValuePair<string, string>("Page",$"{dayPart.Value2} by Store(DB)"),
                new KeyValuePair<string, string>("PortalPath","/shared/Dashboard/_portal/Peak Hour Period"),
                new KeyValuePair<string, string>("Action","ApplyFilter"),
                new KeyValuePair<string, string>("ViewID",viewid),
                new KeyValuePair<string, string>("StateAction","samePageState"),
                new KeyValuePair<string, string>("P0",dayPart.Xml ?? ""),
                new KeyValuePair<string, string>("P1","dashboardPage"),
                new KeyValuePair<string, string>("Caller","PortalPages"),
                new KeyValuePair<string, string>("_scid",scid),
                new KeyValuePair<string, string>("icharset","utf-8"),
            });
            return message;
        }

        private HttpRequestMessage RequestPeakHourStep5(string viewState, string xml, string reloadTargets, string pageid, string sid)
        {
            var message = new HttpRequestMessage(HttpMethod.Post, "https://biee.mcdonalds.cn/analytics/saw.dll?Go");
            message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36");
            message.Content = new FormUrlEncodedContent(new[]
           {
                new KeyValuePair<string, string>("ViewState",viewState),
                new KeyValuePair<string, string>("Done",$"PortalPages&PortalPath=%2Fshared%2FDashboard%2F_portal%2FPeak%20Hour%20Period&Page={dayPart.Value}%20by%20Store(DB)&ViewState={viewState}"),
                new KeyValuePair<string, string>("ClientStateXml",xml),
                new KeyValuePair<string, string>("fmapId","GxBopg"),
                new KeyValuePair<string, string>("reloadTargets",reloadTargets),
                new KeyValuePair<string, string>("Page",$"{dayPart.Value2} by Store(DB)"),
                new KeyValuePair<string, string>("PortalPath","/shared/Dashboard/_portal/Peak Hour Period"),
                new KeyValuePair<string, string>("Action","Navigate"),
                new KeyValuePair<string, string>("ViewID",""),
                new KeyValuePair<string, string>("Path","/shared/Sales/R08.Peak Hour Rpt by Store(DB)"),
                new KeyValuePair<string, string>("PageID",pageid),
                new KeyValuePair<string, string>("P0","<sawx:expr xmlns:sawx=\"com.siebel.analytics.web/expression/v1.1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"sawx:logical\" op=\"and\"><sawx:expr xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"sawx:comparison\" op=\"equal\"><sawx:expr xsi:type=\"sawx:sqlExpression\">\"Operation\".\"Store Name\"</sawx:expr><sawx:expr xsi:type=\"sawx:untypedLiteral\">1420040 Kaiping Tanj</sawx:expr></sawx:expr><sawx:expr xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"sawx:comparison\" op=\"equal\"><sawx:expr xsi:type=\"sawx:sqlExpression\">'分层次日期选择'</sawx:expr><sawx:expr xsi:type=\"sawx:untypedLiteral\">分层次日期选择</sawx:expr></sawx:expr></sawx:expr>"),
                new KeyValuePair<string, string>("P19",sid),
                new KeyValuePair<string, string>("P17",""),
                new KeyValuePair<string, string>("P16","NavRuleDefault"),
                new KeyValuePair<string, string>("NavFromViewID",$"{reloadTargets}~v:compoundView!1~v:pivotTableView!1"),
                new KeyValuePair<string, string>("P18","frd"),
            });
            return message;
        }

        private HttpRequestMessage RequestPeakHourStep6(string viewState2, string viewState, string xml, string pageid, string vid, string scid)
        {
            var message = new HttpRequestMessage(HttpMethod.Post, "https://biee.mcdonalds.cn/analytics/saw.dll?reloadAnalysis");
            message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36");
            message.Content = new FormUrlEncodedContent(new[]
           {
                new KeyValuePair<string, string>("ViewState",viewState2),
                new KeyValuePair<string, string>("Done",$"PortalPages&PortalPath=%2Fshared%2FDashboard%2F_portal%2FPeak%20Hour%20Period&Page={dayPart.Value}%20by%20Store(DB)&ViewState={viewState}"),
                new KeyValuePair<string, string>("ClientStateXml",xml),
                new KeyValuePair<string, string>("fmapId","GxBopg"),
                new KeyValuePair<string, string>("Page",$"{dayPart.Value2} by Store(DB)"),
                new KeyValuePair<string, string>("PageID",pageid),
                new KeyValuePair<string, string>("Path","/shared/Sales/R08.Peak Hour Rpt by Store(DB)"),
                new KeyValuePair<string, string>("Action",""),
                new KeyValuePair<string, string>("ViewID",vid),
                new KeyValuePair<string, string>("ViewPos","compoundView!1"),
                new KeyValuePair<string, string>("_scid",scid),
                new KeyValuePair<string, string>("icharset","utf-8"),
            });
            return message;
        }


        /// <summary>
        /// 下载前准备
        /// </summary>
        private HttpRequestMessage RequestPeahHourStep7(string vid, string sid, string viewstate, string xml)
        {
            var message = new HttpRequestMessage(HttpMethod.Post, "https://biee.mcdonalds.cn/analytics/saw.dll?Go");
            message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36");
            DateTimeOffset now = DateTimeOffset.Now;
            string timestamp = now.ToUnixTimeMilliseconds().ToString();
            message.Content = new FormUrlEncodedContent(new[]
           {
                new KeyValuePair<string, string>("ViewID",vid),
                new KeyValuePair<string, string>("Action","Download"),
                new KeyValuePair<string, string>("SearchID",sid),
                new KeyValuePair<string, string>("fmapId","GxBopg"),
                new KeyValuePair<string, string>("ViewState",viewstate),
                new KeyValuePair<string, string>("ItemName","R08.Peak Hour Rpt by Store(DB)"),
                new KeyValuePair<string, string>("path","/shared/Sales/R08.Peak Hour Rpt by Store(DB)"),
                new KeyValuePair<string, string>("Format","excel2007"),
                new KeyValuePair<string, string>("Extension",".xlsx"),
                new KeyValuePair<string, string>("DownloadId",timestamp),
                new KeyValuePair<string, string>("clientStateXml",xml)
            });
            return message;
        }

        private HttpRequestMessage RequestPeakHourStep8(string status, string scid)
        {
            var message = new HttpRequestMessage(HttpMethod.Post, "https://biee.mcdonalds.cn/analytics/saw.dll?DownloadJobStatus");
            message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36");
            message.Content = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("d",status),
                new KeyValuePair<string, string>("ItemName","R08.Peak Hour Rpt by Store(DB)"),
                new KeyValuePair<string, string>("DummyInt","2"),
                new KeyValuePair<string, string>("_scid",scid),
                new KeyValuePair<string, string>("icharset","utf-8")                
            });
            return message;
        }

        /// <summary>
        /// 下载
        /// </summary>
        /// <returns></returns>
        private HttpRequestMessage RequestPeakHourStep9(string status)
        {
            var message = new HttpRequestMessage(HttpMethod.Get, $"https://biee.mcdonalds.cn/analytics/saw.dll?downloadExcelFile&d={status}&ItemName=R08.Peak%20Hour%20Rpt%20by%20Store(DB)");
            return message;
        }

        private static string GetXml(string content)
        {
            string pattern = @"<nqw[^>]*>(.*?)</nqw>";
            Match match = Regex.Match(content, pattern);
            string xml = match.Groups[1].Value;
            xml = xml.Replace("\\u003c", "<");
            xml = xml.Replace("\\\"", "\"");
            pattern = @"<sawst:stateRef>(.*?)</sawst:stateRef>";
            match = Regex.Match(xml, pattern, RegexOptions.Singleline);
            xml = match.Groups[1].Value;
            return xml;
        }

    }
}
